package net.maku.events.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fhs.trans.service.impl.TransService;
import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
import lombok.AllArgsConstructor;
import net.maku.events.dao.*;
import net.maku.events.entity.*;
import net.maku.events.enums.ActivityTypeEnum;
import net.maku.events.service.ActivityBriskWalkSiteService;
import net.maku.events.service.UserJoinActivityService;
import net.maku.events.vo.*;
import net.maku.framework.common.utils.*;
import net.maku.framework.mybatis.service.impl.BaseServiceImpl;
import net.maku.events.convert.ActivityBriskWalkConvert;
import net.maku.events.query.ActivityBriskWalkQuery;
import net.maku.events.service.ActivityBriskWalkService;
import net.maku.framework.security.user.SecurityUser;
import net.maku.storage.service.StorageService;
import net.maku.system.convert.SysUserConvert;
import net.maku.system.entity.SysUserEntity;
import net.maku.system.enums.SuperAdminEnum;
import net.maku.system.service.SysOrgService;
import net.maku.system.vo.SysUserExcelVO;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 健步走活动
 *
 * @author 阿沐 babamu@126.com
 * @since 1.0.0 2025-03-22
 */
@Service
public class ActivityBriskWalkServiceImpl extends BaseServiceImpl<ActivityBriskWalkDao, ActivityBriskWalkEntity> implements ActivityBriskWalkService {

    @Autowired
    ActivityBriskWalkSiteService activityBriskWalkSiteService;
    @Autowired
    ActivityBriskWalkFeatureDao activityBriskWalkFeatureDao;
    @Autowired
    UserPointsRecordsDao userPointsRecordsDao;
    @Autowired
    SysOrgService sysOrgService;
    @Autowired
    StorageService storageService;
    @Autowired
    ActivityBriskWalkPointsLadderDao activityBriskWalkPointsLadderDao;
    @Autowired
    TransService transService;
    @Autowired
    UserEarningsCardDao userEarningsCardDao;
    @Autowired
    UserJourneyDao userJourneyDao;
    @Autowired
    ActivityRankSnapshotDao activityRankSnapshotDao;
    @Autowired
    ActivityRankOrgSnapshotDao activityRankOrgSnapshotDao;

    @Value("${wx.appId}")
    private String appId;

    @Value("${wx.appSecret}")
    private String appSecret;

    @Override
    public PageResult<ActivityBriskWalkVO> page(ActivityBriskWalkQuery query) {
        IPage<ActivityBriskWalkEntity> page = baseMapper.selectPage(getPage(query), getWrapper(query));
        List<ActivityBriskWalkVO> result = BeanUtil.copyToList(page.getRecords(), ActivityBriskWalkVO.class);
        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            //判断是否开启站点地图
            Map<Long, Long> siteDataMap = activityBriskWalkSiteService.searchSiteByIdList(result.stream().map(ActivityBriskWalkVO::getId).collect(Collectors.toList()));
            if (ObjectUtils.isNotEmpty(siteDataMap)) {
                result.forEach(item -> {
                    if (ObjectUtils.isNotEmpty(siteDataMap.get(item.getId()))) {
                        item.setEnableDisable(1);
                    }
                });
            }
        }
        return new PageResult<>(result, page.getTotal());
    }

    @Override
    public ActivityBriskWalkVO getInfoById(Long id) {
        ActivityBriskWalkVO activityBriskWalkVO = BeanUtil.copyProperties(this.getById(id), ActivityBriskWalkVO.class);
        activityBriskWalkSiteService.setSiteData(activityBriskWalkVO);
        activityBriskWalkVO.setActivityBriskWalkFeatureList(BeanUtil.copyToList(activityBriskWalkFeatureDao.selectList(new LambdaQueryWrapper<ActivityBriskWalkFeatureEntity>().eq(ActivityBriskWalkFeatureEntity::getBriskWalkId, id)), ActivityBriskWalkFeatureVO.class));
        activityBriskWalkVO.setActivityBriskWalkPointsLadderList(BeanUtil.copyToList(activityBriskWalkPointsLadderDao.selectList(new LambdaQueryWrapper<ActivityBriskWalkPointsLadderEntity>().eq(ActivityBriskWalkPointsLadderEntity::getBriskWalkId, id)), ActivityBriskWalkPointsLadderVO.class));
        return activityBriskWalkVO;
    }

    private LambdaQueryWrapper<ActivityBriskWalkEntity> getWrapper(ActivityBriskWalkQuery query) {
        LambdaQueryWrapper<ActivityBriskWalkEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.isNotEmpty(query.getActivityTitle()), ActivityBriskWalkEntity::getActivityTitle, query.getActivityTitle())
                .eq(ObjectUtils.isNotEmpty(query.getStatus()), ActivityBriskWalkEntity::getActivityStatus, query.getStatus())
                .eq(ObjectUtils.isNotEmpty(query.getActivityStatus()), ActivityBriskWalkEntity::getActivityStatus, query.getActivityStatus())
                .eq(ObjectUtils.isNotEmpty(query.getWhetherTop()), ActivityBriskWalkEntity::getWhetherTop, query.getWhetherTop())
                .orderByDesc(ActivityBriskWalkEntity::getId);
        dataScopeWrapper(wrapper);
        return wrapper;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(ActivityBriskWalkVO vo) {
        sysOrgService.setActivityJoinOrgName(vo);
        ActivityBriskWalkEntity entity = BeanUtil.copyProperties(vo, ActivityBriskWalkEntity.class);
        entity.setOrgId(SecurityUser.getUser().getOrgId());
        baseMapper.insert(entity);
        activityBriskWalkSiteService.insertData(entity.getId(), vo.getActivityBriskWalkSiteList());
        insertActivityBriskWalkFeature(entity.getId(), vo);
        insertPointsLadder(entity.getId(), vo.getActivityBriskWalkPointsLadderList());
    }

    /**
     * 添加积分阶梯
     *
     * @param walkId             健步走id
     * @param pointsLadderVOList 积分阶梯
     */
    private void insertPointsLadder(Long walkId, List<ActivityBriskWalkPointsLadderVO> pointsLadderVOList) {
        if (CollectionUtils.isNotEmpty(pointsLadderVOList)) {
            LambdaQueryWrapper<ActivityBriskWalkPointsLadderEntity> queryWrapper = new LambdaQueryWrapper<ActivityBriskWalkPointsLadderEntity>().eq(ActivityBriskWalkPointsLadderEntity::getBriskWalkId, walkId);
            List<Long> idList = pointsLadderVOList.stream().filter(item -> ObjectUtils.isNotEmpty(item.getId())).map(ActivityBriskWalkPointsLadderVO::getId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(idList)) {
                queryWrapper.notIn(ActivityBriskWalkPointsLadderEntity::getId, idList);
            }
            activityBriskWalkPointsLadderDao.delete(queryWrapper);
            List<ActivityBriskWalkPointsLadderEntity> pointsLadderEntityList = BeanUtil.copyToList(pointsLadderVOList, ActivityBriskWalkPointsLadderEntity.class);
            pointsLadderEntityList.forEach(item -> {
                item.setBriskWalkId(walkId);
            });
            activityBriskWalkPointsLadderDao.insertOrUpdate(pointsLadderEntityList);
        } else {
            activityBriskWalkPointsLadderDao.delete(new LambdaQueryWrapper<ActivityBriskWalkPointsLadderEntity>().eq(ActivityBriskWalkPointsLadderEntity::getBriskWalkId, walkId));
        }
    }


    /**
     * 插入健步走关联活动
     *
     * @param walkId 健步走id
     * @param vo     关联活动
     */
    private void insertActivityBriskWalkFeature(Long walkId, ActivityBriskWalkVO vo) {
        if (CollectionUtils.isNotEmpty(vo.getActivityBriskWalkFeatureList())) {
            LambdaQueryWrapper<ActivityBriskWalkFeatureEntity> queryWrapper = new LambdaQueryWrapper<ActivityBriskWalkFeatureEntity>().eq(ActivityBriskWalkFeatureEntity::getBriskWalkId, walkId);
            List<Long> idList = vo.getActivityBriskWalkFeatureList().stream().filter(item -> ObjectUtils.isNotEmpty(item.getId())).map(ActivityBriskWalkFeatureVO::getId).collect(Collectors.toList());
            if (ObjectUtils.isNotEmpty(idList)) {
                queryWrapper.notIn(ActivityBriskWalkFeatureEntity::getId, idList);
            }
            activityBriskWalkFeatureDao.delete(queryWrapper);
            List<ActivityBriskWalkFeatureEntity> entityList = BeanUtil.copyToList(vo.getActivityBriskWalkFeatureList(), ActivityBriskWalkFeatureEntity.class);
            entityList.forEach(item -> {
                item.setBriskWalkId(walkId);
            });
            activityBriskWalkFeatureDao.insertOrUpdate(entityList);
        } else {
            activityBriskWalkFeatureDao.delete(new LambdaQueryWrapper<ActivityBriskWalkFeatureEntity>().eq(ActivityBriskWalkFeatureEntity::getBriskWalkId, walkId));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ActivityBriskWalkVO vo) {
        sysOrgService.setActivityJoinOrgName(vo);
        ActivityBriskWalkEntity entity = BeanUtil.copyProperties(vo, ActivityBriskWalkEntity.class);
        updateById(entity);
        activityBriskWalkSiteService.updateData(entity.getId(), vo.getActivityBriskWalkSiteList());
        insertActivityBriskWalkFeature(entity.getId(), vo);
        insertPointsLadder(entity.getId(), vo.getActivityBriskWalkPointsLadderList());
    }

    @Override
    public void updateStatus(Long id, Integer status) {
        ActivityBriskWalkEntity entity = new ActivityBriskWalkEntity();
        entity.setId(id);
        entity.setStatus(status);
        baseMapper.updateById(entity);
    }

    @Override
    public void whetherTop(ActivityTopVO activityTopVO) {
        ActivityBriskWalkEntity entity = new ActivityBriskWalkEntity();
        entity.setId(activityTopVO.getActivityId());
        entity.setWhetherTop(activityTopVO.getStatus());
        entity.setTopImg(activityTopVO.getTopImg());
        baseMapper.updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteInfoById(List<Long> idList) {
        removeByIds(idList);
        activityBriskWalkSiteService.deleteByIdList(idList);
    }

    @Override
    public String createWxQr(ActivityShareQrVO activityShareQrVO) {
        OutputStream stream = null;
        try {
            //获取AccessToken
            String accessToken = WeiXinUtils.getAccessToken(appId, appSecret);
            //设置响应类型
            String urls = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + accessToken;
            //组装参数
            Map<String, Object> paraMap = new HashMap<>();
            //二维码携带参数 不超过32位 参数类型必须是字符串
            paraMap.put("scene", activityShareQrVO.getParam());
            //二维码跳转页面
            paraMap.put("page", activityShareQrVO.getPage());
            //二维码的宽度
            paraMap.put("width", 450);
            //自动配置线条颜色，如果颜色依然是黑色，则说明不建议配置主色调
            paraMap.put("auto_color", false);
            //是否需要透明底色， is_hyaline 为true时，生成透明底色的小程序码
            paraMap.put("is_hyaline", false);
            URL url = new URL(urls);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setRequestMethod("POST");// 提交模式
            httpURLConnection.setConnectTimeout(10000);//连接超时 单位毫秒
            httpURLConnection.setReadTimeout(10000);//读取超时 单位毫秒
            // 发送POST请求必须设置如下两行
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
            printWriter.write(JSON.toJSONString(paraMap));
            // flush输出流的缓冲
            printWriter.flush();

            //HuaweiObsUtil使用华为存储bos（自行封装）
            String name = System.currentTimeMillis() + ".png";
            String path = storageService.getPath(name);
            InputStream inputStream = httpURLConnection.getInputStream();
            String fileUrl = storageService.upload(inputStream, path);
            ActivityBriskWalkEntity activityBriskWalkEntity = new ActivityBriskWalkEntity();
            activityBriskWalkEntity.setId(activityShareQrVO.getActivityId());
            activityBriskWalkEntity.setWxShareQr(fileUrl);
            this.updateById(activityBriskWalkEntity);
            return fileUrl;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    @Override
    public void exportUserRanks(Long id) {
        List<RankMemberUserExportVO> userExportVOList = BeanUtil.copyToList(activityRankSnapshotDao.selectList(new LambdaQueryWrapper<ActivityRankSnapshotEntity>().eq(ActivityRankSnapshotEntity::getActivityId, id)
                .eq(ActivityRankSnapshotEntity::getBusinessType, ActivityTypeEnum.WALK_ACTIVITY.getBusinessType())
                .orderByDesc(ActivityRankSnapshotEntity::getPoints)
                .orderByDesc(ActivityRankSnapshotEntity::getStepNumber)
                .orderByDesc(ActivityRankSnapshotEntity::getCardNumber)
                .orderByAsc(ActivityRankSnapshotEntity::getAcquireCardTime)), RankMemberUserExportVO.class);
        transService.transBatch(userExportVOList);
        //获取总步数
        if (CollectionUtils.isNotEmpty(userExportVOList)) {
            for (int i = 0; i < userExportVOList.size(); i++) {
                userExportVOList.get(i).setRanks(i + 1);
            }
        }
        // 写到浏览器打开
        ExcelUtils.excelExport(RankMemberUserExportVO.class, "个人排行", null, userExportVOList);

//        List<RankMemberUserVO> result = userPointsRecordsDao.getRankPage(id, ActivityTypeEnum.WALK_ACTIVITY.getBusinessType());
//        List<RankMemberUserExportVO> userExportVOList = BeanUtil.copyToList(result, RankMemberUserExportVO.class);
//        transService.transBatch(userExportVOList);
//        //获取总步数
//        if (CollectionUtils.isNotEmpty(userExportVOList)) {
//            List<Long> userIdList = userExportVOList.stream().map(RankMemberUserExportVO::getId).collect(Collectors.toList());
//            List<UserJourneyEntity> journeyEntityList = userJourneyDao.selectList(new LambdaQueryWrapper<UserJourneyEntity>()
//                    .in(UserJourneyEntity::getUserId, userIdList)
//                    .eq(UserJourneyEntity::getWalkActivityId, id));
//            if (CollectionUtils.isNotEmpty(journeyEntityList)) {
//                Map<Long, Long> journeyMap =
//                        journeyEntityList.stream().collect(Collectors.groupingBy(UserJourneyEntity::getUserId, Collectors.summingLong(e ->
//                                Optional.of(e.getStepNumber()).orElse(0L))));
//                userExportVOList.forEach(item -> {
//                    item.setTotalStep(journeyMap.getOrDefault(item.getId(), 0L));
//                });
//            }
//            for (int i = 0; i < userExportVOList.size(); i++) {
//                userExportVOList.get(i).setRanks(i + 1);
//            }
//        }
//        // 写到浏览器打开
//        ExcelUtils.excelExport(RankMemberUserExportVO.class, "个人排行", null, userExportVOList);
    }

//    @Override
//    public void exportUserRanks(Long id) {
//        List<RankMemberUserVO> result = userPointsRecordsDao.getRank(id, ActivityTypeEnum.WALK_ACTIVITY.getBusinessType());
//        List<RankMemberUserExportVO> userExportVOList = BeanUtil.copyToList(result, RankMemberUserExportVO.class);
//        transService.transBatch(userExportVOList);
//        if (CollectionUtils.isNotEmpty(userExportVOList)) {
//            List<Long> userIdList = userExportVOList.stream().map(RankMemberUserExportVO::getId).collect(Collectors.toList());
//            Long cardNumber = activityBriskWalkSiteService.getCardNumber(id);
//            if (cardNumber.intValue() != 0) {
//                //获取总步数
//                List<UserJourneyEntity> journeyEntityList = userJourneyDao.selectList(new LambdaQueryWrapper<UserJourneyEntity>()
//                        .in(UserJourneyEntity::getUserId, userIdList)
//                        .eq(UserJourneyEntity::getWalkActivityId, id));
//                if (CollectionUtils.isNotEmpty(journeyEntityList)) {
//                    Map<Long, Long> journeyMap =
//                            journeyEntityList.stream().collect(Collectors.groupingBy(UserJourneyEntity::getUserId, Collectors.summingLong(e ->
//                                    Optional.of(e.getStepNumber()).orElse(0L))));
//                    userExportVOList.forEach(item -> {
//                        item.setTotalStep(journeyMap.getOrDefault(item.getId(), 0L));
//                    });
//                }
//                //获取集卡数量
//                setCardInfo(cardNumber.intValue(), id, userIdList, userExportVOList);
//                if (CollectionUtils.isNotEmpty(userExportVOList)) {
//                    Comparator<RankMemberUserExportVO> comparator = Comparator
//                            .comparingDouble(RankMemberUserExportVO::getPoints).reversed() // 积分降序（最高优先）
//                            .thenComparing(Comparator.comparingLong(RankMemberUserExportVO::getCardNumber).reversed())  // 集卡数降序
//                            .thenComparing(RankMemberUserExportVO::getCompletionTime, Comparator.nullsLast(Comparator.naturalOrder()))  // 时间戳降序（最近优先）
//                            .thenComparing(RankMemberUserExportVO::getTime, Comparator.nullsLast(Comparator.naturalOrder()));  // 最后时间降序
//                    userExportVOList.sort(comparator);
//                    for (int i = 0; i < userExportVOList.size(); i++) {
//                        userExportVOList.get(i).setRanks(i + 1);
//                    }
//                }
//            }
//        }
//        // 写到浏览器打开
//        ExcelUtils.excelExport(RankMemberUserExportVO.class, "个人排行", null, userExportVOList);
//    }

    /**
     * 设置卡片获取信息
     *
     * @param cardNumber       卡片数量
     * @param id               健步走id
     * @param userIdList       参与该健步走的用户id数组
     * @param userExportVOList 待导出的数据
     */
    private void setCardInfo(int cardNumber, Long id, List<Long> userIdList, List<RankMemberUserExportVO> userExportVOList) {
        List<UserEarningsCardEntity> earningsCardEntityList =
                userEarningsCardDao.selectList(new LambdaQueryWrapper<UserEarningsCardEntity>().eq(UserEarningsCardEntity::getBriskWalkId, id).in(UserEarningsCardEntity::getUserId, userIdList));
        if (CollectionUtils.isNotEmpty(earningsCardEntityList)) {
            Map<Long, List<UserEarningsCardEntity>> earningsCardMap = earningsCardEntityList.stream().collect(Collectors.groupingBy(UserEarningsCardEntity::getUserId));
            userExportVOList.forEach(item -> {
                item.setPoints(item.getPoints() > 20 ? 20 : item.getPoints());
                List<UserEarningsCardEntity> earningsCardEntities = earningsCardMap.get(item.getId());
                if (CollectionUtils.isNotEmpty(earningsCardEntities)) {
                    item.setCardNumber(earningsCardEntities.size());
                    if (earningsCardEntities.size() == cardNumber) {
                        Collections.sort(earningsCardEntities);
                        item.setAcquireCardTime(earningsCardEntities.get(cardNumber - 1).getCreateTime());
                    }
                }
            });
        }
    }


    @Override
    public void exportOrgRanks(Long id) {
        List<RankOrgExportVO> rankOrgExportVOS = BeanUtil.copyToList(activityRankOrgSnapshotDao.selectList(new LambdaQueryWrapper<ActivityRankOrgSnapshotEntity>().eq(ActivityRankOrgSnapshotEntity::getActivityId, id)
                .orderByAsc(ActivityRankOrgSnapshotEntity::getRanks)), RankOrgExportVO.class);
        // 写到浏览器打开
        Comparator<RankOrgExportVO> comparator = Comparator
                .comparingDouble(RankOrgExportVO::getPoints).reversed()
                .thenComparing(Comparator.comparingLong(RankOrgExportVO::getCardNumber).reversed());
        rankOrgExportVOS.sort(comparator);
        for (int i = 0; i < rankOrgExportVOS.size(); i++) {
            rankOrgExportVOS.get(i).setRanks(i + 1);
        }
        ExcelUtils.excelExport(RankOrgExportVO.class, "工会排行", null, rankOrgExportVOS);
//        List<RankOrgVO> result = userPointsRecordsDao.getRankOrg(id, ActivityTypeEnum.WALK_ACTIVITY.getBusinessType());
//        List<RankOrgExportVO> rankOrgExportVOS = BeanUtil.copyToList(result, RankOrgExportVO.class);
//        // 写到浏览器打开
//        Comparator<RankOrgExportVO> comparator = Comparator
//                .comparingDouble(RankOrgExportVO::getPoints).reversed()
//                .thenComparing(Comparator.comparingLong(RankOrgExportVO::getCardNumber).reversed());
//        rankOrgExportVOS.sort(comparator);
//        for (int i = 0; i < rankOrgExportVOS.size(); i++) {
//            rankOrgExportVOS.get(i).setRanks(i + 1);
//        }
//        ExcelUtils.excelExport(RankOrgExportVO.class, "工会排行", null, rankOrgExportVOS);
    }

}